﻿/***
    Copyright 2012 Stijn Van Antwerpen

    This file is part of Qasparov.

    Qasparov is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Qasparov is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Qasparov. If not, see <http://www.gnu.org/licenses/>.

 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Qbus.Communication;
using System.Threading;
using Qbus.Communication.Protocol;
using Qbus.Communication.Protocol.Commands;

namespace DirectCommand
{
    class Program
    {
        static Controller controller = new Controller();
            
        static void Main(string[] args)
        {
            Init();

            //ContinueAfterLoaded

           
        }

        private static void ContinueAfterLoaded()
        {
            String cmd = Console.ReadLine();
            while(!cmd.Equals("exit"))
            {
                Process(cmd);
                cmd = Console.ReadLine();
            }
            ConnectionManager.Instance.DisconnectAll();
        }

        private static void Process(String cmd)
        {
            var c = cmd.Split(new char[]{' '},2);
            if (c[0].Equals("show"))
            {
                Show(c[1]);
            }else if(c[0].Equals("set")) 
            {
                Set(c[1]);
            }
            else if (c[0].Equals("invoke"))
            {
                Invoke(c[1]);
            }
            else if (c[0].Equals("list"))
            {
                List();
            }
            else if (c[0].Equals("generate"))
            {
                //QBusAPIGenerator.Generate("MyQBus.cs", controller);
            }


        }

        private static void List()
        {
            foreach (var m in controller.Modules)
            {
                Console.WriteLine("{0} ({1}/{2})",
                    m.Name,
                    m.Address,
                    m.Subaddress);
            }
        }

        private static void Invoke(string p)
        {
            var c = p.Split(new char[] { ' ' });
            var moduleName = c[0];
            var methodeName = c[1];

            var module = controller.Modules.First(m => m.Name.Equals(moduleName));
            var methode = module.GetType().GetMethod(methodeName);

            methode.Invoke(module, new object[] { });
            
        }

        private static void Set(string p)
        {
            var c = p.Split(new char[]{' '});
            var moduleName = c[0];
            var propertyName = c[1];
            var propertyValueString = c[2];

            var module = controller.Modules.First(m => m.Name.Equals(moduleName));
            var property = module.GetType().GetProperty(propertyName);
            if (property.CanWrite)
            {

                var t = Nullable.GetUnderlyingType(property.PropertyType);
                if (t == null) // This means PropertyType is not Nullable
                {
                    t = property.PropertyType;
                }

                var propertyValue = Convert.ChangeType(propertyValueString, t);

                property.SetValue(module, propertyValue, null);
            }
            else {
                Console.WriteLine("Property {0} is read only.", propertyName); 
            }
        }

        private static void Show(string p)
        {
            var module = controller.Modules.FirstOrDefault(m => m.Name.Equals(p));
            EchoObject(module);
        }


        private static void Init()
        {
            Console.WriteLine("Starting...");

            controller.Address = "qavanna.servebeer.com";
            controller.Login = "admin";
            controller.Password = "Pixy";

            ConnectionManager.Instance.Modules.GetModules += new GetModulesAsyncResult(Modules_GetModules);
            ConnectionManager.Instance.onError += new ConnectionManager.ErrorEventHandler(Instance_onError);
            ConnectionManager.Instance.ConnectionChanged += new EventHandler(Instance_ConnectionChanged);
            ConnectionManager.Instance.CommandReceived += new ControllerCommunication.CommandEventHandler(Instance_CommandReceived);


            Console.WriteLine("Connecting...");

            ConnectionManager.Instance.Connect(controller);

            Thread.Sleep(2000);
            Console.WriteLine("Connected.");

            ConnectionManager.Instance.Modules.GetModulesAsync();

        }

  


        static void Instance_CommandReceived(object sender, CommandEventArgs e)
        {
            Console.ForegroundColor = ConsoleColor.Blue;
            //Console.WriteLine("CommandReceived.");
            EchoObject(e.Command);
            Console.ResetColor();
        }

        private static void EchoObject(object obj)
        {

            if (obj != null)
            {
                var props = obj.GetType().GetProperties().OrderBy(p => p.Name);
                var meth = obj.GetType().GetMethods().Where(m => m.GetParameters().Count() == 0).OrderBy(m => m.Name);
                Console.WriteLine(obj.GetType());
                foreach (var prop in props)
                {
                    try
                    {
                        if (prop.CanRead)
                        {
                            Console.WriteLine(String.Format("{0}: {1} {2}",
                                prop.Name,
                                prop.GetValue(obj, null),
                                prop.CanWrite?"":"read only"
                                ));
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                }
                foreach (var m in meth)
                {
                    Console.WriteLine("{0} {1}({2})"
                        , m.ReturnParameter
                        , m.Name
                        ,"");
                }
            }
            else {
                Console.WriteLine("null");
            }
            Console.WriteLine();

        }

      
        static void Instance_ConnectionChanged(object sender, EventArgs e)
        {
            Console.WriteLine("ConnectionChanged.");
        }

    

        static void Instance_onError(object sender, ConnectionManager.ErrorEventArgs args)
        {
            Console.WriteLine("onError.");
            Console.ForegroundColor = ConsoleColor.Red;
            EchoObject(args);
            Console.ResetColor();
        }

        static bool continueOnce = true;
        static void Modules_GetModules(List<Qbus.Communication.Protocol.Module> modules)
        {
            Console.WriteLine("Modules Loaded.");
            if (continueOnce)
            {
                continueOnce = false;
                ContinueAfterLoaded();
            }
        }

   
    }
}
